package com.briup.es.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.briup.es.auth.SecurityUserContext;
import com.briup.es.config.exception.ServiceException;
import com.briup.es.config.response.ResultCode;
import com.briup.es.domain.bean.Book;
import com.briup.es.domain.bean.Category;
import com.briup.es.domain.bean.Collect;
import com.briup.es.domain.dto.BookChangeNumDTO;
import com.briup.es.domain.vo.BookDetailVO;
import com.briup.es.domain.vo.BookVO;
import com.briup.es.mapper.CategoryMapper;
import com.briup.es.mapper.CollectMapper;
import com.briup.es.service.BookService;
import com.briup.es.mapper.BookMapper;
import com.briup.es.util.BeanUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

@Service
@RequiredArgsConstructor
public class BookServiceImpl extends ServiceImpl<BookMapper, Book>
        implements BookService {

    private final CategoryMapper categoryMapper;
    private final CollectMapper collectMapper;

    @Override
    public List<BookVO> showBooksLimit20() {
        // 查询到的图书必须是处于上架状态的
        LambdaQueryWrapper<Book> wrapper = new LambdaQueryWrapper<Book>()
                .eq(Book::getStatus, 0);
        List<Book> books = baseMapper.selectList(wrapper);
        // 随机获取前20本图书，用于模拟热门推荐的动态性，并返回数据
        List<Book> bookList = books.subList(0, Math.min(books.size(), 20));
        Collections.shuffle(bookList);
        // 进行bean转换并返回数据
        return BeanUtil.bean2VOS(bookList, BookVO.class);
    }

    @Override
    public List<BookVO> findByCategoryId(Integer id) {
        // 查询到的图书必须是处于上架状态的
        LambdaQueryWrapper<Book> wrapper = new LambdaQueryWrapper<Book>()
                .eq(Book::getStatus, 0)
                .eq(Book::getCategoryId, id);
        List<Book> books = baseMapper.selectList(wrapper);
        return BeanUtil.bean2VOS(books, BookVO.class);
    }

    @Override
    public List<BookVO> searchBook(String query) {
        // 构建查询的条件，根据查询关键字是否传输，决定对书籍名称、描述、作者、出版社等内容就行模糊查询
        LambdaQueryWrapper<Book> wrapper = new LambdaQueryWrapper<Book>()
                .eq(Book::getStatus, 0)
                .like(StringUtils.hasText(query), Book::getName, query)
                .or()
                .like(StringUtils.hasText(query), Book::getDescription, query)
                .or()
                .like(StringUtils.hasText(query), Book::getAuthor, query)
                .or()
                .like(StringUtils.hasText(query), Book::getPublisher, query);
        // 根据条件查询出符合条件的数据集合
        List<Book> books = baseMapper.selectList(wrapper);
        return BeanUtil.bean2VOS(books, BookVO.class);
    }

    @Override
    public BookDetailVO queryBookDetailById(Integer id) {
        LambdaQueryWrapper<Book> wrapper = new LambdaQueryWrapper<Book>()
                .eq(Book::getStatus, 0)
                .eq(Book::getId, id);
        Book book = baseMapper.selectOne(wrapper);
        // 转换为BookDetailVO对象
        BookDetailVO detailVO = BeanUtil.bean2VO(book, BookDetailVO.class);

        Category category = categoryMapper.selectById(book.getCategoryId());
        // 设置栏目的名称
        detailVO.setCategoryName(category.getName());
        // 设置本图书是否被当前用户收藏
        Integer userId = SecurityUserContext.currentUserId();
        // 根据图书id和用户id查询对应的收藏是否存在
        LambdaQueryWrapper<Collect> queryWrapper = new LambdaQueryWrapper<Collect>()
                .eq(Collect::getBookId, detailVO.getId())
                .eq(Collect::getUserId, userId);
        Collect collect = collectMapper.selectOne(queryWrapper);
        // 不为null表示被收藏，为null表示未被收藏
        detailVO.setCollect(!Objects.isNull(collect));
        return detailVO;
    }

    @Override
    public void changeStoreNum(List<BookChangeNumDTO> dtoList) {
        // 遍历需要修改的数据，一一修改对应商品的库存
        for (BookChangeNumDTO bookChangeNumDTO : dtoList) {
            LambdaQueryWrapper<Book> wrapper = new LambdaQueryWrapper<Book>()
                    .eq(Book::getStatus, 0)
                    .eq(Book::getId, bookChangeNumDTO.getBookId());
            Book book = baseMapper.selectOne(wrapper);
            Integer changeNum = bookChangeNumDTO.getChangeNum();
            // 图书为null 以及变化量为负数时，需要抛出异常；
            // 因为变化量为负数此时表示生成订单，如果图书不存在或已下架就无法生成订单
            if (book == null) {
                if (changeNum <= 0) {
                    throw new ServiceException(ResultCode.BOOK_IS_NOT_EXISTS);
                } else {
                    return;
                }
            } else {
                // 如果book不为null，那么说明该图书商品存在并且还处于上架状态，那么生成订单时就需要确保该订单的库存足够
                // 计算商品变化后的库存
                book.setStoreNum(book.getStoreNum() + changeNum);
                // 确保生成订单时，商品的库存大于等于用户购买的商品数量
                if (book.getStoreNum() < 0) {
                    throw new ServiceException(ResultCode.BOOK_STORE_NUM_IS_NULL);
                }
            }
            // 在确保上述操作无误后，就可以修改图书商品的库存
            LambdaUpdateWrapper<Book> updateWrapper = new LambdaUpdateWrapper<Book>()
                    .set(Book::getStoreNum, book.getStoreNum())
                    .eq(Book::getId, book.getId());
            baseMapper.update(updateWrapper);
        }
    }

    @Override
    public BookVO queryById(Integer id) {
        LambdaQueryWrapper<Book> wrapper = new LambdaQueryWrapper<Book>()
                .eq(Book::getStatus, 0)
                .eq(Book::getId, id);
        Book book = baseMapper.selectOne(wrapper);
        return BeanUtil.bean2VO(book,BookVO.class);
    }

    @Override
    public List<BookVO> queryByIds(List<Integer> ids) {
        LambdaQueryWrapper<Book> wrapper = new LambdaQueryWrapper<Book>()
                .eq(Book::getStatus, 0)
                .in(Book::getId, ids);
        List<Book> books = baseMapper.selectList(wrapper);
        return BeanUtil.bean2VOS(books,BookVO.class);
    }
}




